﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TinyEngine.Core.Parsers;
using System.IO;
using System.Xml.Linq;
using TinyEngine.Core.Services;
using TinyEngine.Core.Asset;
using Microsoft.Xna.Framework;

namespace TinyEngine.Core.Entities.Parsers
{
    public class TileGridParser : IEntityParser
    {
        public System.Xml.Linq.XElement ToXmlElement(IEntity obj)
        {
            var root = new XElement(obj.GetType().Name);
            var tgrid = obj as TileGridEntity;

            ParserHelper.ParseIEntityToXml(obj, root);

            ParserHelper.ParseAssetHolderToXML<SpriteAsset>(obj, root);
            root.SetAttributeValue("Ref", tgrid.FileRef);
            return root;
        }

        public IEntity FromXmlElement(System.Xml.Linq.XElement element)
        {
            var tileGrid = new TileGridEntity();
            ParserHelper.ParseXmlToIEntity(element, tileGrid);

            var fileRef = ParserHelper.TryParseString("Ref", element);
            tileGrid.FileRef = fileRef;

            var assetRoot = ServiceManager.GetService<AssetLibrary>().GetContentRoot();
            fileRef = Path.Combine(assetRoot, fileRef);
            TileGridFileParser.LoadDataFromFile(fileRef, tileGrid);

            SetOrigin(tileGrid);
            LoadAssets(tileGrid);
            return tileGrid;
        }

        private void SetOrigin(TileGridEntity tileGrid)
        {
            var x = tileGrid.TilesX * tileGrid.TileSizeX;
            var y = tileGrid.TilesY * tileGrid.TileSizeY;

            tileGrid.Origin = new Microsoft.Xna.Framework.Vector2(x / 2, y / 2);
        }

        private void LoadAssets(TileGridEntity tileGrid)
        {
            var assetLib = Services.ServiceManager.GetService<Services.AssetLibrary>();
            var copy = tileGrid.AssetList.ToArray();
            foreach (var item in copy)
            {
                tileGrid.AssetList[item.Key] = assetLib.GetSprite(item.Key);
            }


        }
    }

    internal class TileGridFileParser
    {
        public static void LoadDataFromFile(string filename, TileGridEntity tileGrid)
        {
            Stream stream = null;
            if (TinyGame.IsInEditor)
                stream = File.OpenRead(filename);
            else
                stream = TitleContainer.OpenStream(filename);

            Parse(stream, tileGrid);
        }
        
        public static void Parse(Stream stream, TileGridEntity tileGrid)
        {
            using (var data = new StreamReader(stream))
            {
                while (!data.EndOfStream)
                {
                    var lineData = data.ReadLine();
                    if (lineData.StartsWith("*"))
                    {
                        //This is the tile data. Parse it into tiles
                        ParseTileData(data.ReadToEnd(), tileGrid);
                    }
                    else
                    {
                        SetData(lineData, tileGrid);
                    }
                }
            }
        }

        private static void ParseTileData(string data, TileGridEntity tileGrid)
        {
            var lines = ParseIntoLines(data);
            int x = 0;
            int y = 0;
            foreach (var item in lines)
            {
                if (item == "*")
                    break;

                var cols = item.Split(' ');
                foreach (var col in cols)
                {
                    if (col == " " || col == "")
                        continue;

                    if (col == ".")
                    {
                        tileGrid.Tiles.Add(new Tile()
                        {
                            IndexX = x,
                            IndexY = y,
                            ImageIndex = -1
                        });
                    }

                    else
                    {
                        tileGrid.Tiles.Add(new Tile()
                        {
                            IndexX = x,
                            IndexY = y,
                            ImageIndex = int.Parse(col)
                        });
                    }
                    x++;
                }
                y++;
                x = 0;
            }
        }

        private static string[] ParseIntoLines(string data)
        {
            var list = new List<string>();
            var items = data.Split('\n');
            foreach (var item in items)
            {
                list.Add(item.Replace("\r", ""));
            }
            return list.ToArray<string>();
        }

        private static void SetData(string lineData, TileGridEntity tileGrid)
        {
            var data = lineData.ToUpper();
            if (data.StartsWith("SIZE"))
            {
                var items = data.Split('=');
                var sizeData = items[1].Split('X');
                tileGrid.TilesX = int.Parse(sizeData[0]);
                tileGrid.TilesY = int.Parse(sizeData[1]);
            }
            if (data.StartsWith("ASSETNAME"))
            {
                var items = lineData.Split('=');
                var name = items[1];
                tileGrid.AssetList.Add(name, null);
            }

            if (data.StartsWith("TILESIZE"))
            {
                var items = data.Split('=');
                var sizeData = items[1].Split('X');
                tileGrid.TileSizeX = int.Parse(sizeData[0]);
                tileGrid.TileSizeY = int.Parse(sizeData[1]);
            }
        }
    }
}
